//#include "length.h"
#include "platform_mmu.h"
#include "PAL.h"
#include "OSProc.h"
#include "MMU.h"
using namespace MM;

extern "C" void __SetFPBaseAddr(unsigned int*);
extern "C" void _MMUSetState(_ptlong*);
extern "C" void _CPUSetState(_ptlong*);

#define MMU_ENABLE
#define MMU_DISABLE

typedef __PageTbl<0,20,12> PageTbl;


#define _AlignPhyMem(x)  (x & ((~0) << PAGE_SIZE_OFFSET))
#define _AlignFlags(x)   (x & ((~0) >> (_PTLONG_OFFSET - PAGE_SIZE_OFFSET)))


  inline int PageFlTblInit(_ptlong** flPage)
  {
    *flPage = PageTbl::PageTblInit();
    return 1;
  }
  /* int PageInit(_ptlong** flPage, _ptlong vAddr)
  {
    
  }*/
  //FlPage , SlPage is all automatically allocated
  inline int CPUSet(unsigned int flag)
  {
    _CPUSetState(flag);
  }
    
  inline int MMU_INIT()
  {
    
  }
  
  inline int MMUEnable()
  {
    _MMUSetState(MMU_ENABLE);
  }

  inline int MMUDisable()
  {
    _MMUSetState(MMU_DISABLE);
  }
  inline int MMUSet(_ptlong flag)
  {
    _MMUSetState(flag);
  }

  inline int MMUMemoryMap(unsigned int* flpage,unsigned int* phyMem,unsigned int* vMem,_ptlong flags)
  {
    *(PageTbl::PDAddr(flpage,vMem)) = _AlignPhyMem(phyMem) | _AlignFlags(flags);
  }
  inline int MMUMemroySet(unsigned int* flpage,unsigned int* vMem,_ptlong flag)
  {
    *(PageTbl::PDAddr(flpage,vMem)) &= _AlignPhyMem((~0));
    *(PageTbl::PDAddr(flpage,vMem)) |= _AlignFlags(flag);
  }
  inline int MMUMemoryEqual(unsigned int* flPageA,unsigned int* vMemA,unsigned int* flPageB,unsigned int* vMemB)
  {//A = B, '='is a copy symbol
    *(PageTbl::PDAddr(flPageA,vMemA)) = *(PageTbl::PDAddr(flPageB,vMemB));
  }
  /* int MMUMemoryUnmap(unsigned int* phyMem)
  {//Problem
    
  }*/
  inline unsigned int* MMUGetPMem(unsigned int* flpage, unsigned int* vMem)
  {
    return (((_ptlong)(PageTbl::PDAddr(flpage,vMem))) + _AlignFlags(((_ptlong)vMem)));
  }
  inline _ptlong MMUGetState(_ptlong* flpage,unsigned int* vMem)
  {
    return *(PageTbl::PDAddr(flpage,vMem));
  }
  inline int MMUSetVMem(unsigned int* flpage,unsigned int* vMem, unsigned int flags)
  {
    return MMUMemorySet(flpage,vMem,flags);
  }
  
  inline int HaveVisitedPMemory(unsigned int* phymem)
  {
    return MM::HaveVisitedMemory(phymem);
  }

  inline int MMUSetFPBaseAddr(unsigned int* phymem)
  {
    __SetFPBaseAddr(phymem);
    return 1;
  }

